package com.itaming.lycheeframework.support.utils;

import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import org.springframework.lang.NonNull;
import org.springframework.util.Assert;
import org.springframework.util.StreamUtils;

import java.io.*;
import java.nio.charset.Charset;

/**
 * IO工具类
 *
 * @author A.Ming
 */
@Slf4j
@UtilityClass
public class IoUtil extends StreamUtils {

    /**
     * 关闭资源
     *
     * @param closeable 可关闭对象
     */
    public static void close(Closeable closeable) {
        if (closeable == null) {
            return;
        }

        if (closeable instanceof Flushable) {
            try {
                ((Flushable) closeable).flush();
            } catch (IOException e) {
                log.warn("Flush error", e);
            }
        }

        try {
            closeable.close();
        } catch (IOException e) {
            log.warn("Close error", e);
        }
    }

    /**
     * 拷贝输入流到字符串
     *
     * @param input InputStream
     * @return 字符串
     */
    public static String copyToString(InputStream input) {
        return copyToString(input, CharsetUtil.getDefault());
    }

    /**
     * 拷贝输入流到字符串
     *
     * @param input   InputStream
     * @param charset 字符集
     * @return 字符串
     */
    public static String copyToString(InputStream input, @NonNull Charset charset) {
        try {
            if (input == null) {
                return StringPool.EMPTY;
            } else {
                Assert.notNull(charset, "Charset must not be null");
                StringBuilder out = new StringBuilder(4096);
                InputStreamReader reader = new InputStreamReader(input, CharsetUtil.defaultIfNull(charset));
                char[] buffer = new char[4096];

                int charsRead;
                while ((charsRead = reader.read(buffer)) != -1) {
                    out.append(buffer, 0, charsRead);
                }

                return out.toString();
            }
        } catch (IOException e) {
            throw new IllegalStateException("I/O error when reading to string", e);
        } finally {
            close(input);
        }
    }

    /**
     * 转为 InputStreamReader
     *
     * @param input InputStream
     * @return InputStreamReader
     */
    public static InputStreamReader toInputStreamReader(InputStream input) {
        Assert.notNull(input, "Input must not be null");
        return new InputStreamReader(input, CharsetUtil.getDefault());
    }

    /**
     * 转为 InputStreamReader
     *
     * @param input   InputStream
     * @param charset 字符集
     * @return InputStreamReader
     */
    public static InputStreamReader toInputStreamReader(InputStream input, Charset charset) {
        Assert.notNull(input, "Input must not be null");
        return new InputStreamReader(input, CharsetUtil.defaultIfNull(charset));
    }

    /**
     * 转为 BufferedReader
     *
     * @param input InputStream
     * @return BufferedReader
     */
    public static BufferedReader toBufferedReader(InputStream input) {
        return new BufferedReader(toInputStreamReader(input));
    }

    /**
     * 转为 BufferedReader
     *
     * @param input   InputStream
     * @param charset 字符集
     * @return BufferedReader
     */
    public static BufferedReader toBufferedReader(InputStream input, Charset charset) {
        return new BufferedReader(toInputStreamReader(input, charset));
    }

}
